
namespace FileCollection
{
    using System;
    using System.IO;
    using System.Security.Cryptography;

    public static class Hash
    {
        /// <summary>
        ///  Gera um Hash de um arquivo utilizando SHA1 como Provider padrao
        /// </summary>
        /// <param name="arquivo"></param>
        /// <returns></returns>
        public static byte[] CalculaHash(FileInfo arquivo)
        {
            return CalculaHash(arquivo, new SHA1CryptoServiceProvider());
        }

        public static byte[] CalculaHash(string arquivo)
        {
            return CalculaHashDoArquivo(arquivo, new SHA1CryptoServiceProvider());
        }

        public static byte[] CalculaHash(FileInfo arquivo, HashAlgorithm hash)
        {
            return CalculaHashDoArquivo(arquivo.FullName, hash);
        }

        public static byte[] CalculaHash(byte[] buffer)
        {
            return CalculaHash(buffer, new SHA1CryptoServiceProvider());
        }

        #region Metodos Padroes
        private static byte[] CalculaHash(Stream stream, HashAlgorithm hash)
        {
            return hash.ComputeHash(stream);
        }

        private static byte[] CalculaHash(byte[] buffer, HashAlgorithm hash)
        {
            return hash.ComputeHash(buffer);
        }

        private static byte[] CalculaHashDoArquivo(string arquivo, HashAlgorithm hash)
        {            
            if (arquivo == null)
            {
                throw new ArgumentNullException("arquivo");
            }
            
            FileStream fs = null;
            byte[] result;
            try
            {
                fs = new FileStream(arquivo, FileMode.Open, FileAccess.Read, FileShare.Read, 8192);
                result = CalculaHash(fs, hash);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }

            return result;
        }
        #endregion
    }
}
